Webhooks

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

Webhooks are custom HTTP callbacks triggered by an event such as pushing code to a repository or posting a comment on an issue. Webhooks send JSON data about the event to the URI configured for the webhook. For more information about these events and the JSON data sent in the webhook payload, see webhook events.

You can use webhooks to:

GitLab.com enforces webhook limits, including:

  • The maximum number of webhooks and their size, both per project and per group.
  • The number of webhook calls per minute.

Group webhooks

Tier: Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

You can configure a group webhook, which is triggered by events that occur across all projects in the group and its subgroups. If you configure identical webhooks in a group and a project, they are both triggered by an event in the project.

Group webhooks can also be configured to listen for events that are specific to a group, including:

Configure webhooks in GitLab

Create a webhook

To create a webhook for a project or group:

  1. In your project or group, on the left sidebar, select Settings > Webhooks.
  2. Select Add new webhook.
  3. In URL, enter the URL of the webhook endpoint. The URL must be percent-encoded if it contains one or more special characters.
  4. Optional. In Secret token, enter the secret token to validate requests.
  5. In the Trigger section, select the events to trigger the webhook.
  6. Optional. Clear the Enable SSL verification checkbox to disable SSL verification.
  7. Select Add webhook.

Mask sensitive portions of webhook URLs

History

You can define and mask sensitive portions of webhook URLs and replace them with configured values any number of times when webhooks are executed. Sensitive portions do not get logged and are encrypted at rest in the database.

To mask sensitive portions of the webhook URL:

  1. In your project or group, on the left sidebar, select Settings > Webhooks.
  2. In URL, enter the full webhook URL.
  3. Select Mask portions of URL.
  4. In Sensitive portion of URL, enter the portion you want to mask.
  5. In How it looks in the UI, enter the masking value.

To interpolate sensitive portions for each webhook, use url_variables. For example, if a webhook has the following URL:

https://webhook.example.com/{path}?key={value}

You must define the following variables:

  • path
  • value

Variable names must contain only lowercase letters (a-z), numbers (0-9), or underscores (_). You can define URL variables directly with the REST API. The host portion of the URL (such as webhook.example.com) must remain valid without using a mask variable. Otherwise, a URI is invalid error occurs.

Custom headers

History

You can add up to 20 custom headers in the webhook configuration as part of the request. You can use these custom headers for authentication to external services.

Custom headers must not override the values of delivery headers. The header name must:

  • Contain only alphanumeric characters, periods, dashes, or underscores.
  • Start with a letter and end with a letter or number.
  • Have no consecutive periods, dashes, or underscores.

Custom headers appear in Recent events with masked values.

Custom webhook template

History

You can set a custom payload template in the webhook configuration. The request body is rendered from the template with the data for the current event. The template must render as valid JSON.

You can use any field from the payload of any event, such as {{build_name}} for a job event and {{deployable_url}} for a deployment event. To access properties nested in objects, specify the path segments separated with .. For example:

Given this custom payload template:

{
  "event": "{{object_kind}}",
  "project_name": "{{project.name}}"
}

You’ll have this request payload that combines the template with a push event:

{
  "event": "push",
  "project_name": "Example"
}

Validate requests with a secret token

You can specify a secret token to validate webhook requests. The token is sent with the hook request in the X-Gitlab-Token HTTP header. Your webhook endpoint can check the token to verify that the request is legitimate.

Filter push events by branch

You can filter push events by branch. Use one of the following options to filter which push events are sent to your webhook endpoint:

  • All branches: push events from all branches.
  • Wildcard pattern: push events from a branch that matches a wildcard pattern (for example, *-stable or production/*).
  • Regular expression: push events from a branch that matches a regular expression (regex). The regex pattern must follow the RE2 syntax. For example, to exclude main, you can use:

    \b(?:m(?!ain\b)|ma(?!in\b)|mai(?!n\b)|[a-l]|[n-z])\w*|\b\w{1,3}\b|\W+
    

To configure branch filtering for a project or group, see Configure a webhook in GitLab

View webhook request history

History
  • Recent events for group webhooks introduced in GitLab 15.3.

Prerequisites:

  • For project webhooks, you must have at least the Maintainer role for the project.
  • For group webhooks, you must have the Owner role for the group.

GitLab records the history of each webhook request. In Recent events, you can view all requests made to a webhook in the last two days.

To view the request history for a webhook:

  1. On the left sidebar, select Search or go to and find your project or group.
  2. Select Settings > Webhooks.
  3. Select Edit for the webhook.
  4. Go to the Recent events section.

The table includes the following details about each request:

  • HTTP status code (green for 200-299 codes, red for the others, and internal error for failed deliveries)
  • Triggered event
  • Elapsed time of the request
  • Relative time for when the request was made

Recent deliveries

Inspect request and response details

Prerequisites:

  • For project webhooks, you must have at least the Maintainer role for the project.
  • For group webhooks, you must have the Owner role for the group.

Each webhook request in Recent events has a Request details page. This page contains the body and headers of:

  • The response GitLab received from the webhook receiver endpoint
  • The webhook request GitLab sent

To inspect the request and response details of a webhook event:

  1. On the left sidebar, select Search or go to and find your project or group.
  2. Select Settings > Webhooks.
  3. Select Edit for the webhook.
  4. Go to the Recent events section.
  5. Select View details for the event.

To send the request again with the same data, select Resend Request. If the webhook URL has changed, you cannot resend the request.

Webhook receiver requirements

Webhook receiver endpoints should be fast and stable. Slow and unstable receivers might be disabled automatically to ensure system reliability. Webhooks that fail might lead to duplicate events.

Endpoints should follow these best practices:

  • Respond quickly with a 200 or 201 status response. Avoid any significant processing of webhooks in the same request. Instead, implement a queue to handle webhooks after they are received. Webhook receivers that do not respond before the timeout limit might be disabled automatically on GitLab.com.
  • Be prepared to handle duplicate events. In some circumstances, the same event may be sent twice. To mitigate this issue, ensure your endpoint is reliably fast and stable.
  • Keep the response headers and body minimal. GitLab does not examine the response headers or body. GitLab stores them so you can examine them later in the logs to help diagnose problems. You should limit the number and size of headers returned. You can also respond to the webhook request with an empty body.
  • Only return client error status responses (in the 4xx range) to indicate that the webhook has been misconfigured. Responses in this range might cause your webhooks to be disabled automatically. For example, if your receiver only supports push events, you can return 400 if sent an issue payload, as that is an indication that the hook has been set up incorrectly. Alternatively, you can ignore unrecognized event payloads.
  • Never return 500 server error status responses if the event has been handled. These responses might cause the webhook to be disabled automatically.
  • Invalid HTTP responses are treated as failed requests.

Webhook timeout limits

For GitLab.com, the timeout limit for webhooks is 10 seconds. For GitLab self-managed, an administrator can change the webhook timeout limit.

Auto-disabled webhooks

History
On self-managed GitLab, by default this feature is not available. To make it available, an administrator can enable the feature flag named auto_disabling_web_hooks. On GitLab.com, this feature is available. On GitLab Dedicated, this feature is not available.

Project or group webhooks that fail four consecutive times are disabled automatically.

To view auto-disabled webhooks:

  1. On the left sidebar, select Search or go to and find your project or group.
  2. Select Settings > Webhooks.

An auto-disabled webhook appears in the list of project or group webhooks as:

Badges on failing webhooks

Temporarily disabled webhooks

Project or group webhooks that return response codes in the 5xx range or experience a timeout or other HTTP errors are considered to be failing intermittently and are temporarily disabled. These webhooks are initially disabled for one minute, which is extended on each subsequent failure up to a maximum of 24 hours.

You can re-enable temporarily disabled webhooks manually if the webhook receiver no longer returns an error.

Permanently disabled webhooks

Project or group webhooks that return response codes in the 4xx range are considered to be misconfigured and are permanently disabled.

These webhooks remain disabled until you re-enable them manually.

Re-enable disabled webhooks

History
  • Introduced in GitLab 15.2 with a flag named webhooks_failed_callout. Disabled by default.
  • Generally available in GitLab 15.7. Feature flag webhooks_failed_callout removed.

To re-enable a temporarily or permanently disabled webhook manually, send a test request.

The webhook is re-enabled if the test request returns a response code in the 2xx range.

Test a webhook

You can trigger a webhook manually, to ensure it’s working properly. You can also send a test request to re-enable a disabled webhook.

For example, to test push events, your project should have at least one commit. The webhook uses this commit in the webhook.

note
Testing is not supported for some types of events for project and groups webhooks. For more information, see issue 379201.

Prerequisites:

  • To test project webhooks, you must have at least the Maintainer role for the project.
  • To test group webhooks, you must have the Owner role for the group.

To test a webhook:

  1. In your project or group, on the left sidebar, select Settings > Webhooks.
  2. Scroll down to the list of configured webhooks.
  3. From the Test dropdown list, select the type of event to test.

You can also test a webhook from its edit page.

Webhook testing

Delivery headers

History
  • X-Gitlab-Event-UUID header introduced in GitLab 14.8.
  • X-Gitlab-Instance header introduced in GitLab 15.5.
  • X-Gitlab-Webhook-UUID header introduced in GitLab 16.2.

Webhook requests to your endpoint include the following headers:

Header Description Example
User-Agent User agent in the format "Gitlab/<VERSION>". "GitLab/15.5.0-pre"
X-Gitlab-Instance Hostname of the GitLab instance that sent the webhook. "https://gitlab.com"
X-Gitlab-Webhook-UUID Unique ID per webhook. "02affd2d-2cba-4033-917d-ec22d5dc4b38"
X-Gitlab-Event Name of the webhook type. Corresponds to event types but in the format "<EVENT> Hook". "Push Hook"
X-Gitlab-Event-UUID Unique ID per webhook that is not recursive. A hook is recursive if triggered by an earlier webhook that hit the GitLab instance. Recursive webhooks have the same value for this header. "13792a34-cac6-4fda-95a8-c58e00a3954e"

Debug webhooks

To debug GitLab webhooks and capture payloads, you can use:

For information about webhook events and the JSON data sent in the webhook payload, see webhook events.

Public webhook inspection and testing tools

You can use public tools to inspect and test webhook payloads. These tools act as catch-all endpoints for HTTP requests and respond with a 200 OK HTTP status code. You can use these payloads to develop your webhook services.

You should exercise caution when using these tools as you might be sending sensitive data to external tools. You should use test tokens with these tools and rotate any secrets inadvertently sent to a third party. To keep your webhook payloads private, create a private webhook receiver instead.

These public tools include:

GitLab Development Kit (GDK)

For a safer development environment, you can use the GitLab Development Kit (GDK) to develop against GitLab webhooks locally. With the GDK, you can send webhooks from your local GitLab instance to a webhook receiver running locally on your machine. To use this approach, you must install and configure the GDK.

Create a private webhook receiver

Prerequisites:

  • You must have Ruby installed.

If you cannot send webhook payloads to a public receiver, you can create your own private webhook receiver.

To create a private webhook receiver:

  1. Save the following file as print_http_body.rb:

    require 'webrick'
    
    server = WEBrick::HTTPServer.new(:Port => ARGV.first)
    server.mount_proc '/' do |req, res|
      puts req.body
    end
    
    trap 'INT' do
      server.shutdown
    end
    server.start
    
  2. Choose an unused port (for example, 8000) and start the script:

    ruby print_http_body.rb 8000
    
  3. In GitLab, configure the webhook and add your receiver’s URL, for example, http://receiver.example.com:8000/.

  4. Select Test. You should see something like this in the console:

    {"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>}
    example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0
    - -> /
    
note
You may need to allow requests to the local network for this receiver to be added.

How image URLs are displayed in the webhook body

Relative image references are rewritten to use an absolute URL in the body of a webhook. For example, if an image, merge request, comment, or wiki page includes the following image reference:

![image](/uploads/$sha/image.png)

If:

  • GitLab is installed at gitlab.example.com.
  • The project is at example-group/example-project.

The reference is rewritten in the webhook body as follows:

![image](https://gitlab.example.com/example-group/example-project/uploads/$sha/image.png)

Image URLs are not rewritten if:

  • They already point to HTTP, HTTPS, or protocol-relative URLs.
  • They use advanced Markdown features like link labels.

Configure webhooks to support mutual TLS

Offering: Self-managed, GitLab Dedicated
History

Prerequisites:

  • You must be a GitLab administrator.

You can configure webhooks to support mutual TLS by configuring a client certificate in PEM format. This certificate is set globally and presented to the server during a TLS handshake. The certificate can also be protected with a PEM passphrase.

To configure the certificate, follow the instructions below.

Linux package (Omnibus)
  1. Edit /etc/gitlab/gitlab.rb:

    gitlab_rails['http_client']['tls_client_cert_file'] = '<PATH TO CLIENT PEM FILE>'
    gitlab_rails['http_client']['tls_client_cert_password'] = '<OPTIONAL PASSWORD>'
    
  2. Save the file and reconfigure GitLab:

    sudo gitlab-ctl reconfigure
    
Docker
  1. Edit docker-compose.yml:

    version: "3.6"
    services:
      gitlab:
        image: 'gitlab/gitlab-ee:latest'
        restart: always
        hostname: 'gitlab.example.com'
        environment:
          GITLAB_OMNIBUS_CONFIG: |
             gitlab_rails['http_client']['tls_client_cert_file'] = '<PATH TO CLIENT PEM FILE>'
             gitlab_rails['http_client']['tls_client_cert_password'] = '<OPTIONAL PASSWORD>'
    
  2. Save the file and restart GitLab:

    docker compose up -d
    
Self-compiled (source)
  1. Edit /home/git/gitlab/config/gitlab.yml:

    production: &base
      http_client:
        tls_client_cert_file: '<PATH TO CLIENT PEM FILE>'
        tls_client_cert_password: '<OPTIONAL PASSWORD>'
    
  2. Save the file and restart GitLab:

    # For systems running systemd
    sudo systemctl restart gitlab.target
    
    # For systems running SysV init
    sudo service gitlab restart
    

Troubleshooting

Unable to get local issuer certificate

When SSL verification is enabled, you might get an error that GitLab cannot verify the SSL certificate of the webhook endpoint. Typically, this error occurs because the root certificate isn’t issued by a trusted certification authority as determined by CAcert.org.

If that is not the case, consider using SSL Checker to identify faults. Missing intermediate certificates are common causes of verification failure.

Webhook fails or multiple webhook requests are triggered

If you’re receiving multiple webhook requests, the webhook might have timed out.

Webhook is not triggered

History
  • Webhooks not triggered in Silent Mode introduced in GitLab 16.3.

If a webhook is not triggered, check that: